﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using EF5;
using System.Data.Entity.Validation;

namespace DataContextLayer
{
    public class Login:DatabaseHelper
    {
        
        private const int MAX_FAILS_ALLOWED = 3;
        protected int FailCount { get; set; }


        public Login()
        {
            
        }

        public bool LogMeIn()
        {

            using (var context = new DclContext())
            {
                if (CheckUserExists())
                {
                    Messages = "success";
                    return true;
                }
                
                return false;
            }

        }

        public bool CheckUserExists()
        {
            using (Context = new DclContext())
            {
                var checkUserExists = Context.Users.Any(u => u.UserName == UserName);

                if (checkUserExists)
                {
                    return CheckAccountLock();
                }
                return false;
            }
        }

        public bool CheckAccountLock()
        {
            using (Context = new DclContext())
            {
                var user = Context.Users.Where(u => u.UserName.Equals(UserName)).ToList();

                var userAcountLocked = user.ElementAt(0).UserAcountLocked;

                var userPasswordReset = user.ElementAt(0).UserPasswordReset;

                FailCount = user.ElementAt(0).FailedLoginAttempts;

                ResetId = user.ElementAt(0).UserId;

                if (userAcountLocked && userPasswordReset)
                {
                    if (DoLoginValuesMatch())
                    {
                        Status = LoginStatus.Reset;
                        Messages = "Please enter your new password in the Password box";
                        //throw new InvalidLoginException("Please enter your new password in the Password box");
                        return false;
                    }
                    Status = LoginStatus.Locked;
                    //throw new InvalidLoginException("Your Account is locked \n Use the password provided by email");
                    Messages = "Your Account is locked \n Use the password provided by email";
                    return false;
                }

                Status = LoginStatus.Pass;

                return DoLoginValuesMatch();
            }
        }

        public bool DoLoginValuesMatch()
        {
            using (Context = new DclContext())
            {

                if (FailCount >= MAX_FAILS_ALLOWED)
                {
                    RunTasks.RunWorkerAsync();

                    
                    Messages = "Emailing user a new password!\n Your Account is now locked";

                    return false;
                }



                var tempPassword = GetSha1Hash(UserPassword);
                var user = Context.Users.Where(u => u.UserName.Equals(UserName) &&
                                                    u.UserPassword.Equals(tempPassword));

                if (IsNotEmpty(user))
                {
                    foreach (var userValue in user)
                    {
                        _userId = userValue.UserId;
                        UserName = userValue.UserName;
                        UserPassword = userValue.UserPassword;
                        UserPasswordReset = userValue.UserPasswordReset;
                        UserAccountLocked = userValue.UserAcountLocked;
                    }
                    return true;
                }

                var userId = Context.Users.Find(ResetId);

                if (Status != LoginStatus.Locked)
                {
                    Context.Entry(userId).Property(u => u.FailedLoginAttempts).CurrentValue += 1;
                }

                Messages = "UserName or Password is incorrect";

                SaveToDb(Context);

                

                return false;
            }
        }

        [Serializable()]
        public class InvalidLoginException : System.Exception
        {
            public InvalidLoginException() : base() { }
            public InvalidLoginException(string message) : base(message) { }
            public InvalidLoginException(string message, System.Exception inner) : base(message, inner) { }

            // A constructor is needed for serialization when an 
            // exception propagates from a remoting server to the client.  
            protected InvalidLoginException(System.Runtime.Serialization.SerializationInfo info,
                System.Runtime.Serialization.StreamingContext context) { }
        }
    }
}
